package com.mtr.databoard.domain.components;

import com.mtr.databoard.common.linqlist.LinqList;
import com.mtr.databoard.domain.resources.ContextResource;
import com.mtr.databoard.domain.resources.FileContent;
import com.mtr.databoard.domain.resources.ResourceEntity;
import com.mtr.databoard.domain.resources.ResourceStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Component
public class ComponentManager {
    private IComponentRepository componentRepository;
    private ResourceStore resourceStore;

    public ComponentManager(@Autowired IComponentRepository componentRepository, @Autowired ResourceStore resourceStore) {
        this.componentRepository = componentRepository;
        this.resourceStore = resourceStore;
    }

    /**
     * 更新组件
     *
     * @param componentId
     * @param cover
     * @param name
     * @param code
     * @param description
     * @param size
     * @param resources
     * @param headLinks
     * @param codes
     * @param customerOptions
     */
    public void update(UUID componentId, ViewResource cover, String name, String code, String description, Size size, List<ViewResource> resources, String headLinks, String codes,String htmlbody,CustomerOptions customerOptions) throws IOException {
        if (!componentRepository.existsById(componentId)) return;
        ViewComponent component = componentRepository.findById(componentId).get();
        ViewResource oldCover = component.getCover();
        ResourceEntity currentEntity = new ResourceEntity(ViewComponent.class.getName(), componentId.toString());

        var contextResources = new ArrayList<ContextResource>();

        if (oldCover != null || cover != null || !oldCover.getFileId().equals(cover.getFileId())) {
            //解除绑定中间件文件
            if (oldCover != null) {
                resourceStore.unbindEntity(oldCover.getFileId(), currentEntity);
            }
            //绑定中间件文件
            if (cover != null) {
                resourceStore.bindEntity(cover.getFileId(), currentEntity);
            }
        }
        //绑定中间件文件
        if (cover != null) {
            contextResources.add(new ContextResource(cover.getFileId(), cover.getFileName()));
        }
        LinqList<ViewResource> newResourceLinqList = new LinqList<>(resources);
        List<ViewResource> oldResources = component.getResources();
        LinqList<ViewResource> oldResourceLinqList = new LinqList<>(oldResources);

        //新列表不包含旧的，则解绑
        oldResourceLinqList.foreach(oldResource -> {
            ViewResource newRresource = newResourceLinqList.firstOrDefault(obj -> oldResource.getFileId().equals(obj.getFileId()));
            if (newRresource == null)
                resourceStore.unbindEntity(oldResource.getFileId(), currentEntity);
        });
        //旧资源不包含新的，则加绑定
        newResourceLinqList.foreach(r -> {
            ViewResource oldRresource = oldResourceLinqList.firstOrDefault(obj -> r.getFileId().equals(obj.getFileId()));
            if (oldRresource == null)
                resourceStore.bindEntity(r.getFileId(), currentEntity);
        });
        component.update(cover, name, code, description, size, resources, headLinks, codes,htmlbody,customerOptions);
        //重新释放资源
        for (ViewResource resource : resources) {
            contextResources.add(new ContextResource(resource.getFileId(), resource.getFileName()));
        }
        resourceStore.releaseResources(contextResources, "compreview", componentId.toString(), true);
        componentRepository.save(component);
    }

    /**
     * 复制组件
     *
     * @param componentId
     * @return
     * @throws CloneNotSupportedException
     */
    public ViewComponent copy(UUID componentId) throws CloneNotSupportedException, IOException {
        ViewComponent component = componentRepository.findById(componentId).get();
        component = component.copy();
        ResourceEntity currentEntity = new ResourceEntity(ViewComponent.class.getName(), component.getId().toString());


        var contextResources = new ArrayList<ContextResource>();
        if (component.getCover() != null) {
            resourceStore.bindEntity(component.getCover().getFileId(), currentEntity);
            contextResources.add(new ContextResource(component.getCover().getFileId(), component.getCover().getFileName()));
        }
        LinqList<ViewResource> newResourceLinqList = new LinqList<>(component.getResources());
        newResourceLinqList.foreach(resource -> {
            resourceStore.bindEntity(resource.getFileId(), currentEntity);
            contextResources.add(new ContextResource(resource.getFileId(), resource.getFileName()));
        });

        //重新释放资源
        resourceStore.releaseResources(contextResources, "compreview", componentId.toString(), true);
        componentRepository.insert(component);
        return component;
    }

    /**
     * 获取组件的所有资源id
     *
     * @param component
     * @return
     */
    private List<String> getResourceIdFromComponent(ViewComponent component) {
        List<String> resourceIds = new ArrayList<>();
        var view = component;
        if (view.getCover() != null)
            resourceIds.add(view.getCover().getFileId());
        if (view.getResources() != null) {
            var resuources = view.getResources();
            for (var resource : resuources) {
                resourceIds.add(resource.getFileId());
            }
        }
        return resourceIds;
    }


    /**
     * 删除
     * @param componentId
     */
    public void delete(UUID componentId) {
        ViewComponent component = componentRepository.findById(componentId).get();
        if (component == null) return;
        ResourceEntity currentEntity = new ResourceEntity(ViewComponent.class.getName(), componentId.toString());
        if(component.getCover()!=null)
            resourceStore.unbindEntity(component.getCover().getFileId(), currentEntity);
        LinqList<ViewResource> resourceLinqList = new LinqList<>(component.getResources());
        resourceLinqList.foreach(r -> {
            resourceStore.unbindEntity(r.getFileId(), currentEntity);
        });

        componentRepository.deleteById(componentId);
        //清除释放的资源
        resourceStore.clearReleasedResources("compreview", componentId.toString());
    }

}
